<?php
/**
 * ApiBase.class.php
 *
 */

namespace MobileApi;

use Center\User as CUser;
use Passport\Account as PUser;

/**
 *
 * 公用类
 *
 * @ignore
 * @package Lib
 * @author  suning <snsnsky@gmail.com>
 *
 */
class ApiBase
{
    /**
     * 是否app调用
     *
     * @return bool
     */
    public static function isApp()
    {
        if (in_array($GLOBALS['g_appid'], [MOBILE_APPID_IPHONE, MOBILE_APPID_ANDROID]) || !empty($_GET['isapp'])) {
            return true;
        }

        return false;
    }

    /**
     * 检查登陆状态, 并返回UID
     *
     * @param bool $auto       true:登录失败将结束程序并输出结果,false:不会中断程序
     * @param bool $check_nick 是否检查昵称设置, 默认检查
     * @return bool|int
     */
    public static function isLogin($auto = true, $check_nick = false)
    {
        $code = 551;
        $msg = '未登录, 请重新登录后再试!';

        $ssid = self::getAuthString();

        if (!empty($ssid)) {
            ini_set('session.use_cookies', 0);
            session_id($ssid);
            session_start();

            if (empty($_SESSION['uid'])) {
                $decode = Passport::decode($ssid);

                if (!empty($decode['uid']) && is_numeric($decode['uid'])) {
                    $_SESSION['uid'] = $decode['uid'];
                    $_SESSION['pwd_crc'] = $decode['pwd_hash'];
                    $_SESSION['login_count'] = $decode['login_count'];
                    goto succ;
                }
            } else {
                goto succ;
            }
        }

        fail:

        //失败时记录一下日志.
        unset($_SESSION['uid'], $_SESSION['pwd']);

        if ($auto) {
            self::output($code, $msg);
        } else {
            return false;
        }

        succ:

        $puser = PUser::getUserById($_SESSION['uid']);

        if (empty($puser['UserId'])) {
            goto fail;
        }
        if ($puser['Status'] == 0) {
            $msg = '此用户不存在或已被禁止访问, 请与客服联系!';
            goto fail;
        }
        //        if ($userinfo[CUser::FIELD_LOGIN_COUNT] - $_SESSION['login_count'] != 0) {
        //            $code = 552;
        //            $msg = '登录已经失效, 请重新登录';
        //            goto fail;
        //        }

        if ($check_nick === true) {
            $userinfo = CUser::getInfoByIds($_SESSION['uid']);
            if ($userinfo[CUser::FIELD_USER_NICK] == '') {
                $code = 553;
                $msg = '未设置用户名, 请先设置用户名';
                goto fail;
            }
        }

        return $_SESSION['uid'];
    }

    /**
     * 获得用户ID或设备ID，用户ID获取优先
     *
     * @return int|string
     */
    public static function getUid()
    {
        $uid = self::isLogin(false, false);
        if ($uid > 0) {
            return $uid;
        }

        return $GLOBALS['g_deviceid'];
    }

    /**
     * API统一输出函数
     *
     * @param integer      $code   返回代码, 200表示成功
     * @param array|string $result 返回结果
     * @return void
     */
    public static function output($code = 200, $result = [])
    {
        header('Content-type: application/json');

        if ($code === 200 && $result === []) {
            $json = '{"Status": 200, "Result": {}}';
        } else {
            if (is_string($result)) {
                $result = [
                    'ErrorMsg' => $result
                ];
            }
            $json = ['Status' => $code, 'Result' => $result, 'ServerTime' => time()];
            $json = json_encode($json);

            $errno = json_last_error();
            if ($errno != JSON_ERROR_NONE) {
                self::log('json_output', [
                    'errno: ' . $errno,
                    'errmsg: ' . json_last_error_msg(),
                    'result: ' . serialize($result),
                    'trace:' . serialize(debug_backtrace())
                ]);
            }
        }
        exit($json);
    }

    /**
     * 记录日志
     *
     * @param string $path   日志路径, 如果不是以MobileApi/开头则自动加上
     * @param mixed  $params 日志参数, 不传入则记录下所有GET/POST数据
     * @return void
     */
    public static function log($path, $params = false)
    {
        if (strpos($path, 'MobileApi/') !== 0) {
            $path = 'MobileApi/' . $path;
        }
        if ($params === false) {
            $params = [
                'appid: ' . $_GET['appid'],
                'version: ' . $_GET['_v'],
                'method: ' . $_GET['_method'],
                'date:' . date("Y-m-d H:i:s"),
                '$_GET: ' . json_encode($_GET),
                '$_POST: ' . json_encode($_POST)
            ];
        }
        if (!is_array($params)) {
            $params = [$params];
        }

        runtime_log($path, $params);
    }

    /**
     * 获取适配版本信息
     *
     * @param string $ver        版本信息
     * @param string $dir_name   目录名
     * @param string $class_name 类名
     * @return bool|string
     */
    public static function getVerAdapter($ver, $dir_name, $class_name)
    {
        $adapter = loadconf('mobileapi/adapter');
        $name = $dir_name . '.' . $class_name;

        foreach ($adapter['='] as $k => $v) {
            if ($k == $ver && isset($v[$name])) {
                return self::_getAdapterVer($k);
            }
        }

        foreach ($adapter['<='] as $k => $v) {
            if (version_compare($ver, $k, '<=') && isset($v[$name])) {
                return self::_getAdapterVer($k);
            }
        }

        return false;
    }

    /**
     * 格式化版本信息
     *
     * @param string $ver 版本信息
     * @return string
     */
    private static function _getAdapterVer($ver)
    {
        return str_replace('.', '', $ver);
    }

    /**
     * 获取登陆认证字符串
     *
     * @return string
     */
    public static function getAuthString()
    {
        return trim($_SERVER['HTTP_AUTH']);
    }

    /**
     * 返回客户端IP
     *
     * @return string
     */
    protected static function clientIp()
    {
        global $app;

        return $app->ip();
    }

    /**
     * API输出结果处理，字符型数字转为int，null转为''
     * string "35489" => int 35489
     * null => ''
     * [] => {}
     *
     * @param $data
     * @return array
     */
    protected static function formatVar($data)
    {
        $data = is_array($data) ? $data : [$data];
        foreach ($data as & $v) {
            if (is_numeric($v) && is_string($v)) {
                $v = (int)$v;
            } elseif ($v === null) {
                $v = '';
            } elseif ($v === []) {
                $v = (object)[];
            } else {
                if (is_array($v)) {
                    $v = self::formatVar($v);
                }
            }
        }

        return $data;
    }

    /**
     * 记录错误的调用方式
     *
     * @param string $method 方法
     * @param array  $args   参数
     * @return void
     */
    public function __call($method, $args)
    {
        self::log('CallFailed', [
            'API Error',
            "API Class Name:{$args[0]}",
            "API Function Name:{$method}",
            'DATE:' . date("Y-m-d H:i:s"),
            "GET:" . json_encode($_GET),
            "POST:" . json_encode($_POST),
        ]);

        self::output(501, '调用方法不存在');
    }
}